#include "display.h"
#include "font_emoji.h"

#include "lv_examples.h"
#define LCD_H_RES (240)
#define LCD_V_RES (320)

#define LCD_DRAW_BUFF_HEIGHT 50
#define LCD_SPI_NUM (SPI2_HOST)
#define LCD_PIXEL_CLK_HZ (40 * 1000 * 1000)
#define LCD_CMD_BITS (8)
#define LCD_PARAM_BITS (8)
#define LCD_BITS_PER_PIXEL (16)
#define LCD_DRAW_BUFF_DOUBLE (1)
#define LCD_DRAW_BUFF_HEIGHT (50)
#define LCD_BL_ON_LEVEL (1)

/* LCD pins */
#define LCD_GPIO_SCLK (GPIO_NUM_47)
#define LCD_GPIO_MOSI (GPIO_NUM_48)
#define LCD_GPIO_RST (GPIO_NUM_16)
#define LCD_GPIO_DC (GPIO_NUM_45)
#define LCD_GPIO_CS (GPIO_NUM_21)
#define LCD_GPIO_BL (GPIO_NUM_40)

/* LCD IO and panel */
static esp_lcd_panel_io_handle_t lcd_io    = NULL;
static esp_lcd_panel_handle_t    lcd_panel = NULL;

/* LVGL display */
static lv_display_t *lvgl_disp = NULL;

lv_obj_t *label1;
lv_obj_t *label2;

// 声明中文字体
LV_FONT_DECLARE(font_puhui_14_1);
void display_lcd_init(void)
{
    // 背光的配置
    gpio_config_t bk_gpio_config = {
        .mode         = GPIO_MODE_OUTPUT,
        .pin_bit_mask = 1ULL << LCD_GPIO_BL};
    ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));

    const spi_bus_config_t buscfg = {
        .sclk_io_num     = LCD_GPIO_SCLK,
        .mosi_io_num     = LCD_GPIO_MOSI,
        .miso_io_num     = GPIO_NUM_NC,
        .quadwp_io_num   = GPIO_NUM_NC,
        .quadhd_io_num   = GPIO_NUM_NC,
        .max_transfer_sz = LCD_H_RES * LCD_DRAW_BUFF_HEIGHT * sizeof(uint16_t),
    };
    spi_bus_initialize(LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO);

    const esp_lcd_panel_io_spi_config_t io_config = {
        .dc_gpio_num       = LCD_GPIO_DC,
        .cs_gpio_num       = LCD_GPIO_CS,
        .pclk_hz           = LCD_PIXEL_CLK_HZ,
        .lcd_cmd_bits      = LCD_CMD_BITS,     // 命令的位数 8
        .lcd_param_bits    = LCD_PARAM_BITS,   // 给命令的参数的位数: 8
        .spi_mode          = 0,
        .trans_queue_depth = 10,
    };
    esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_NUM, &io_config, &lcd_io);

    const esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = LCD_GPIO_RST,
        .rgb_ele_order  = LCD_RGB_ELEMENT_ORDER_RGB,
        .bits_per_pixel = LCD_BITS_PER_PIXEL,
    };
    esp_lcd_new_panel_st7789(lcd_io, &panel_config, &lcd_panel);

    esp_lcd_panel_reset(lcd_panel);
    esp_lcd_panel_init(lcd_panel);
    esp_lcd_panel_mirror(lcd_panel, true, true);
    esp_lcd_panel_disp_on_off(lcd_panel, true);

    /* LCD backlight on */
    gpio_set_level(LCD_GPIO_BL, LCD_BL_ON_LEVEL);
}

void display_lvgl_init(void)
{
    const lvgl_port_cfg_t lvgl_cfg = {
        .task_priority     = 4,    /* LVGL task priority */
        .task_stack        = 4096, /* LVGL task stack size */
        .task_affinity     = -1,   /* LVGL task pinned to core (-1 is no affinity) */
        .task_max_sleep_ms = 500,  /* Maximum sleep in LVGL task */
        .timer_period_ms   = 5     /* LVGL timer tick period in ms */
    };
    lvgl_port_init(&lvgl_cfg);

    /* Add LCD screen */
    const lvgl_port_display_cfg_t disp_cfg = {
        .io_handle     = lcd_io,
        .panel_handle  = lcd_panel,
        .buffer_size   = LCD_H_RES * LCD_DRAW_BUFF_HEIGHT,
        .double_buffer = LCD_DRAW_BUFF_DOUBLE,
        .hres          = LCD_H_RES,
        .vres          = LCD_V_RES,
        .monochrome    = false,   // 是否单色显示
        .color_format  = LV_COLOR_FORMAT_RGB565,
        .rotation      = {
                 .swap_xy  = false,
                 .mirror_x = true,
                 .mirror_y = true,
        },
        .flags = {
            .buff_dma    = true,
            .swap_bytes  = true,   // 字节序的调整
            .buff_spiram = true    // 是否使用spiram

        }};
    lvgl_disp = lvgl_port_add_disp(&disp_cfg);

    // 显示一个标签
    lv_obj_t *scr = lv_scr_act();

    lvgl_port_lock(0);

    label1 = lv_label_create(scr);
    lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/
    lv_label_set_text(label1, "尚硅谷智能语音聊天机器人");
    lv_obj_set_width(label1, LCD_H_RES); /*Set smaller width to make the lines wrap*/
    lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_align(label1, LV_ALIGN_CENTER, 0, 40);
    lv_obj_set_style_text_font(label1, &font_puhui_14_1, 0);   // 设置字体

    label2 = lv_label_create(scr);
    lv_label_set_long_mode(label2, LV_LABEL_LONG_WRAP); /*Break the long lines*/
    lv_label_set_text(label2, "😴");
    lv_obj_set_width(label2, LCD_H_RES); /*Set smaller width to make the lines wrap*/
    lv_obj_set_style_text_align(label2, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_align(label2, LV_ALIGN_CENTER, 0, -20);
    lv_obj_set_style_text_font(label2, font_emoji_64_init(), 0);   // 设置字体

    lvgl_port_unlock();
}

void display_init(void)
{
    display_lcd_init();
    display_lvgl_init();
}

void display_show_useage(void)
{
    lvgl_port_lock(0);
    lv_label_set_text(label1, "说:\"你好,小智\"来唤醒机器人聊天");
    lvgl_port_unlock();
}

void display_show_tts_stt(char *txt)
{
    lvgl_port_lock(0);
    lv_label_set_text(label1, txt);
    lvgl_port_unlock();
}

typedef struct
{
    char *emotion;
    char *text;

} emoji_t;

static emoji_t emoji_listp[] = {
    {"neutral", "😶"},
    {"happy", "🙂"},
    {"laughing", "😆"},
    {"funny", "😂"},
    {"sad", "😔"},
    {"angy", " 😠"},
    {"crying", "😭"},
    {"loving", "😍"},
    {"embarrassed", "😳"},
    {"surprised", "😯"},
    {"shocked", "😱"},
    {"thinking", "🤔"},
    {"winking", "😉"},
    {"cool", "😎"},
    {"relaxed", "😌"},
    {"delicious", "🤤"},
    {"kissy", "😘"},
    {"confident", "😏"},
    {"sleepy", "😴"},
    {"silly", "😜"},
    {"confused", "🙄"}};

void display_show_emoji(char *emotion)
{
    char *txt = "🤔";
    for(int i = 0; i < sizeof(emoji_listp) / sizeof(emoji_listp[0]); i++)
    {
        if(strcmp(emoji_listp[i].emotion, emotion) == 0)
        {
            txt = emoji_listp[i].text;
            break;
        }
    }

    lvgl_port_lock(0);
    lv_label_set_text(label2, txt);
    lvgl_port_unlock();
}

lv_obj_t *qr;
void      display_show_qr(char *content)
{
    if(qr) return;
    lvgl_port_lock(0);
    lv_color_t bg_color = lv_color_white();
    lv_color_t fg_color = lv_color_black();

    qr = lv_qrcode_create(lv_screen_active());
    lv_qrcode_set_size(qr, 200);
    lv_qrcode_set_dark_color(qr, fg_color);
    lv_qrcode_set_light_color(qr, bg_color);

    /*Set data*/
    lv_qrcode_update(qr, content, strlen(content));
    lv_obj_center(qr);

    /*Add a border with bg_color*/
    lv_obj_set_style_border_color(qr, bg_color, 0);
    lv_obj_set_style_border_width(qr, 5, 0);
    lvgl_port_unlock();
}

void display_del_qr(void)
{
    if(qr)
    {
        lvgl_port_lock(0);
        lv_obj_del(qr);
        lvgl_port_unlock();
        qr = NULL;
    }
}
